// Project name:JavaRedis
// Creator:muhong
// Date time:2022/12/8,11:08 下午
// Name:ServerBootstrap

package org.gmh.server.v2;

import org.gmh.channel.*;
import org.gmh.channel.handler.ChannelHandlerContext;
import org.gmh.channel.handler.ChannelInboundHandlerAdapter;
import org.gmh.channel.handler.ChannelPipeline;
import org.gmh.channel.nio.NioServerSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.ServerSocketChannel;
import java.util.ArrayList;
import java.util.List;

public class ServerBootstrap {
    private final static Logger logger = LoggerFactory.getLogger(ServerBootstrap.class);

    private volatile EventLoopGroup group;

    private volatile EventLoopGroup childGroup;

    List<ChannelHandler> childHandler = new ArrayList<>();

    public ServerBootstrap() {

    }

    public ChannelFuture bind(int port) throws Exception {
        InetSocketAddress address = new InetSocketAddress(port);
        try {
            // 注册server channel到EventLoopGroup中
            logger.info("server init and register to event loop");
            ServerSocketChannel javaChannel = ServerSocketChannel.open();
            javaChannel.bind(address);
            Channel serverChannel = new NioServerSocketChannel(javaChannel);
            init(serverChannel);
            return this.group.register(serverChannel);
        } catch (IOException e) {
            e.printStackTrace();
            throw new Exception(e);
        }
    }

    private void doBind() {
        // NO_OP
    }

    public ServerBootstrap childHandlers(List<ChannelHandler> childHandler) {
        this.childHandler = childHandler;
        return this;
    }

    private void init(Channel channel) {
        logger.info("server init pipeline");
        ChannelPipeline pipeline = channel.pipeline();
        pipeline.addLast(new ServerBootstrapAcceptor(this.childGroup, this.childHandler));
    }

    public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) {

        this.group = parentGroup;
        this.childGroup = childGroup;
        return this;
    }

    private static class ServerBootstrapAcceptor extends ChannelInboundHandlerAdapter {

        private final EventLoopGroup childGroup;

        List<ChannelHandler> childHandler;

        ServerBootstrapAcceptor(EventLoopGroup childGroup, List<ChannelHandler> childHandler) {
            this.childGroup = childGroup;
            this.childHandler = childHandler;
        }

        private static void forceClose(Channel child, Throwable t) {
            child.unsafe().closeForcibly();
            logger.warn("Failed to register a accepted channel:{}", child, t);
        }

        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) {
            logger.info("server handle a accepted client socket");
            // 转换msg为客户端的socket
            final Channel child = (Channel) msg;
            ChannelPipeline pipeline = child.pipeline();
            for (ChannelHandler handler : childHandler) {
                pipeline.addLast(handler);
            }
            // 注册
            try {
                logger.info("The child group info:{}", childGroup);
                childGroup.register(child).addListener(new ChannelFutureListener() {
                    @Override
                    public void operationComplete(ChannelFuture future) throws Exception {
                        if (!future.isSuccess()) {
                            forceClose(future.channel(), future.cause());
                        } else {
                            logger.info("The client channel register successful");
                        }
                    }
                });
            } catch (Throwable t) {
                forceClose(child, t);
            }
        }
    }
}
